package jeconbond.experiment.market.resourcerelations.generate;

import jeconbond.automata.INode;
import jeconbond.automata.Node;
import jeconbond.automata.AutomataUtils;
import jeconbond.automata.AutomataUtils.IProfitCostGenManager;
import jeconbond.experiment.generate.IAutomataGenerator;
import jeconbond.experiment.market.resourcerelations.process.IResourceRelationExperimentContext;
import jeconbond.experiment.market.resourcerelations.BranchingProductionExperimentSettings;
import jeconbond.experiment.process.IJEBExperimentContext;

import java.util.List;

import laboratoryQ.BaseUtils;
import laboratoryQ.computation.IRandom;

public class BranchingProdAutomataGenerator implements IAutomataGenerator {
	@Override
	public INode[] generate(IJEBExperimentContext iexperimentContext) {
		IResourceRelationExperimentContext experimentContext =
			(IResourceRelationExperimentContext) iexperimentContext;
		BranchingProductionExperimentSettings settings = experimentContext.getExperimentSettings();
		INode[] automatas = new INode[settings.agentsCount];
		for (int i = 0; i < settings.agentsCount; i++) {
			IProfitCostGenManager manager =
				settings.profitCostManagerFactory.newManager(experimentContext);
			automatas[i] = generateOne("BrAu:" + i, experimentContext, manager);
			addPostBranching(automatas[i], experimentContext, manager);
		}
		return automatas;
	}

	private INode generateOne(
			String prefix, 
			IResourceRelationExperimentContext experimentContext,
			IProfitCostGenManager manager
	) {
		INode root = new Node(prefix + "root");
		BranchingProductionExperimentSettings settings = experimentContext.getExperimentSettings();
		for (int i = 0; i < settings.branchesCount; i++) {
			AutomataUtils.generateChain(
					root,
					settings.chainLength,
					prefix + "n:" + i,
					manager
					);
			manager.onBranchCompleted();
		}
		return root;
	}
	
	private void addPostBranching(
			INode root, 
			IResourceRelationExperimentContext experimentContext, 
			IProfitCostGenManager manager
	) {
		List<INode> allNodes = AutomataUtils.dfsGetAllNodesList(root);
		allNodes.remove(root);
		int postBranchCount = experimentContext.getExperimentSettings().postBranchCount;
		IRandom random = experimentContext.getRandom();
		for (int i = 0; i < postBranchCount; i++) {
			INode post = (INode) BaseUtils.extractRandomFromList(allNodes, random);
			int length = AutomataUtils.getLengthOfEasyTrace(post, root);
			String prefix = post.getName() + "[br]";
			AutomataUtils.generateChain(post, root, length, prefix, manager);
			manager.onBranchCompleted();
		}
	}
}
